package com.yenlien.traceyun.plant.service;

import com.alibaba.fastjson.JSONObject;
import com.yenlien.traceyun.business.dao.SupplierLogDao;
import com.yenlien.traceyun.business.entity.SupplierLog;
import com.yenlien.traceyun.business.interceptor.UserAuthUtil;
import com.yenlien.traceyun.business.service.rest.usercenter.FileRestService;
import com.yenlien.traceyun.common.utils.Tools;
import com.yenlien.traceyun.plant.bean.CostDTO;
import com.yenlien.traceyun.plant.dao.FarmDao;
import com.yenlien.traceyun.plant.dao.InputsDao;
import com.yenlien.traceyun.plant.dao.InputsLogDao;
import com.yenlien.traceyun.plant.entity.Farm;
import com.yenlien.traceyun.plant.entity.Inputs;
import com.yenlien.traceyun.plant.entity.InputsLog;
import com.yenlien.traceyun.plant.entity.InputsLog.Type;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.*;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.persistence.criteria.*;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.time.temporal.TemporalAdjusters;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Stream;

import static com.yenlien.traceyun.plant.utils.Tools.DATE_TIME_FORMATTER;

@Service
public class InputsService {
    @Autowired
    private InputsDao inputsDao;
    @Autowired
    private InputsLogDao inputsLogDao;
    @Autowired
    private FileRestService fileService;
    @Autowired
    private SupplierLogDao supplierLogDao;

    @Autowired
    private FarmDao farmDao;

    public Object getCost(String startTime, String endTime, String companyId) {
        if (StringUtils.isBlank(companyId)){
            companyId = UserAuthUtil.getLoginUser().getCompanyId();
        }
        List<Inputs> costList = inputsDao.getCost(startTime, endTime, companyId);
        LocalDate startTime1 = LocalDate.parse(startTime).with(TemporalAdjusters.firstDayOfMonth());
        LocalDate endTime1 = LocalDate.parse(endTime).with(TemporalAdjusters.lastDayOfMonth());
        Map<String, String> fertilizer = new HashMap<>();   // 肥料
        Map<String, String> seedlings = new HashMap<>();
        Map<String, String> other = new HashMap<>();
        Map<String, String> pesticide = new HashMap<>();    // 农药
        Stream.iterate(startTime1, d -> d.plusMonths(1)).limit(ChronoUnit.MONTHS.between(startTime1, endTime1) + 1).forEach(f -> {
            String month = f.toString().substring(0, 7);
            for(Inputs inputs : costList){
                if("肥料".equals(inputs.getType())){
                    fertilizer.put(month, inputs.getTotalPrice());
                }
                if("其他".equals(inputs.getType())){
                    other.put(month, inputs.getTotalPrice());
                }
                if("农药".equals(inputs.getType())){
                    pesticide.put(month, inputs.getTotalPrice());
                }
                if("种苗".equals(inputs.getType())){
                    seedlings.put(month, inputs.getTotalPrice());
                }
            }
        });
        JSONObject object = new JSONObject();
        object.put("fertilizer", fertilizer);
        object.put("seedlings", seedlings);
        object.put("other", other);
        object.put("pesticide", pesticide);
        return object;
    }

    public List<Inputs> getCostTable(String startTime, String endTime, String companyId, String type) {
        if (StringUtils.isBlank(companyId)){
            companyId = UserAuthUtil.getLoginUser().getCompanyId();
        }
        return inputsDao.getCostType(startTime, endTime, companyId, type);
    }

    public List<CostDTO> exportCostTable(String startTime, String endTime, String companyId, String type) {
        if (StringUtils.isBlank(companyId)){
            companyId = UserAuthUtil.getLoginUser().getCompanyId();
        }
        return genCostDTO(inputsDao.getCostType(startTime, endTime, companyId, type));
    }

    public List<CostDTO> genCostDTO(List<Inputs> inputsList){
        List<CostDTO> costDTOList = new ArrayList<>();
        for(Inputs inputs : inputsList){
            CostDTO costDTO = CostDTO.custom()
                    .name(inputs.getInputsName())
                    .buyTime(inputs.getBuyTime())
                    .number(inputs.getTotalNumber())
                    .price(inputs.getPrice())
                    .orderNo(inputs.getOrderNo())
                    .totalPrice(inputs.getTotalPrice()).build();
            costDTOList.add(costDTO);
        }
        return costDTOList;
    }





    public Page<Inputs> findByList(final Inputs inputs) {
        Pageable pageable = PageRequest.of(inputs.getPage(), inputs.getPageSize(), Sort.Direction.DESC, ("createtime"));
        return inputsDao.findAll(new Specification<Inputs>() {
            private static final long serialVersionUID = -1396496630802017658L;

            @Override
            public Predicate toPredicate(Root<Inputs> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                Path<String> inputsName = root.get("inputsName");
                Path<String> type = root.get("type");
                //构造查询条件
                List<Predicate> list = new ArrayList<Predicate>();
                list.add(cb.equal(root.get("isDelete"), false));
                if (!StringUtils.isEmpty(inputs.getType())) {
                    list.add(cb.equal(type, inputs.getType()));
                }
                Predicate[] predicateA = new Predicate[list.size()];
                Predicate predicateAnd = cb.and(list.toArray(predicateA));

                if (StringUtils.isNotEmpty(inputs.getInputsName())) {
                    List<Predicate> list2 = new ArrayList<>();
                    list2.add(cb.like(inputsName, "%" + inputs.getInputsName() + "%"));
                    Predicate[] predicateO = new Predicate[list2.size()];
                    Predicate predicateOr = cb.or(list2.toArray(predicateO));
                    return query.where(predicateAnd, predicateOr).getRestriction();
                } else {
                    return predicateAnd;
                }
            }
        }, pageable);
    }

    public Inputs findById(String id) {
        Inputs inputs = inputsDao.findById(id);
        inputs.setList(inputsLogDao.findByInputsId(id));
        return inputs;
    }


    @Transactional
    public void save(Inputs inputs, List<MultipartFile> files) throws Exception {
        String id = inputs.getId();

        inputs.setSurplusNumber(inputs.getTotalNumber());
        fileService.upload(null, inputs, files);
        inputsDao.save(inputs);

        if (StringUtils.isEmpty(id)) {
            // 新增操作
            InputsLog inputsLog = new InputsLog();
            inputsLog.setInputsId(inputs.getId());
            inputsLog.setNumber(inputs.getTotalNumber());
            inputsLog.setUnits(inputs.getUnits());
            inputsLog.setType(Type.IN);
            inputsLog.setUsername(UserAuthUtil.getLoginUser().getUsername());
            inputsLog.setTime(LocalDateTime.now().format(DATE_TIME_FORMATTER));
//            inputsLog.setTime(inputs.getBuyTime());
            inputsLog.setSurplusNum(inputs.getTotalNumber());
            inputsLogDao.save(inputsLog);
        }
        SupplierLog supplierLog = new SupplierLog();
        supplierLog.setSupplierId(inputs.getSupplyId());
        supplierLog.setCreateTime(Tools.getCurrentTime());
        supplierLog.setInputsName(inputs.getInputsName());
        supplierLog.setNumber(inputs.getTotalNumber());
        supplierLog.setSpec(inputs.getSpec());
        supplierLog.setUnits(inputs.getUnits());
        supplierLog.setSpec(inputs.getSpec() + inputs.getSpecUnits());
        supplierLogDao.save(supplierLog);
    }

    @Transactional
    public void save2(Inputs inputs) throws Exception {
        String id = inputs.getId();
        inputs.setSurplusNumber(inputs.getTotalNumber());
        inputsDao.save(inputs);
        if (StringUtils.isEmpty(id)) {
            InputsLog inputsLog = new InputsLog();
            inputsLog.setInputsId(inputs.getId());
            inputsLog.setNumber(inputs.getTotalNumber());
            inputsLog.setUnits(inputs.getUnits());
            inputsLog.setType(Type.IN);
            inputsLog.setUsername(UserAuthUtil.getLoginUser().getUsername());
            inputsLog.setTime(LocalDateTime.now().format(DATE_TIME_FORMATTER));
//            inputsLog.setTime(inputs.getBuyTime());
            inputsLog.setSurplusNum(inputs.getTotalNumber());
            inputsLogDao.save(inputsLog);
        }
        SupplierLog supplierLog = new SupplierLog();
        supplierLog.setSupplierId(inputs.getSupplyId());
        supplierLog.setCreateTime(Tools.getCurrentTime());
        supplierLog.setInputsName(inputs.getInputsName());
        supplierLog.setNumber(inputs.getTotalNumber());
        supplierLog.setSpec(inputs.getSpec());
        supplierLog.setUnits(inputs.getUnits());
        supplierLog.setSpec(inputs.getSpec() + inputs.getSpecUnits());
        supplierLogDao.save(supplierLog);
    }

    public List<Inputs> findAll() {
        return inputsDao.findNotDeleteAll();
    }

    public Page<Inputs> dynamic() {
        Integer page = 0;
        Sort ageSort = Sort.by(Sort.Direction.DESC, "createtime");
        PageRequest pageRequest = PageRequest.of(page, 7, ageSort);
//        String companyId = UserAuthUtil.getLoginUser().getCompanyId();
//        Page<Inputs> all = inputsDao.findAll((Root<Inputs> root, CriteriaQuery<?> query, CriteriaBuilder cb) -> {
//            List<Predicate> list = new ArrayList<>();
//            list.add(cb.equal(root.get("companyId"), companyId));
//            return cb.and(list.toArray(new Predicate[list.size()]));
//        }, pageRequest);
//        return all;
        Page inputsPage = new PageImpl(inputsDao.getByCompanyId(UserAuthUtil.getLoginUser().getCompanyId()));
        return inputsPage;
    }

    public List<Farm> dynamic2(String companyId) {
        return farmDao.getByCompanyId(companyId);
    }


}
